package com.message.tcp.ip.socket.util;

import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.log4j.Logger;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.packager.GenericPackager;

import com.message.tcp.ip.socket.configure.entity.Bin;
import com.message.tcp.ip.socket.configure.entity.CardAccount;
import com.message.tcp.ip.socket.configure.entity.Case;
import com.message.tcp.ip.socket.configure.entity.Member;

public class UtilPackage {
	private static final Logger logger = Logger.getLogger(UtilPackage.class);
	private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
	private static final int LEN = 4;
	// print dump bytes
	public static void printDumpBytes(char[] dump){
		for(int i=0;i<dump.length;i++){
			if(i>0 && i%2==0)
				System.out.printf(" ");
			if(i>0 && i%32==0)
				System.out.printf("\n");
			System.out.printf("%c",dump[i]);
		}
	}
	// extract message from bytes data
	public static byte[] extractMessage(byte[] msg) {
		byte[] header = {msg[0],msg[1],msg[2],msg[3]};
		int len = Integer.parseInt(new String(header));
		byte[] data = new byte[len];
		for(int i=0;i<len;i++){
			data[i] = msg[i+LEN];
		}
		return data;
	}
	// add header to message data
	public static byte[] addHeader(byte[] data){
		int len = data.length;
		String strLen = String.format("%04d", len);
		byte[] header = strLen.getBytes();
		return mergeBytes(header,data);
	}
	// Bytes array merge
	public static byte[] mergeBytes(byte[] a, byte[] b){
		
		int aLen = a.length;
		int bLen = b.length;
		
		int len = aLen+bLen;
		
		byte[] data = new byte[len];
		for(int i=0;i<aLen;i++){
			data[i]=a[i];
		}
		for(int j=0;j<bLen;j++){
			data[j+aLen]=b[j];
		}
		
		return data;
	}
	// hex to string, string to hex
	
    public static String stringToHex(String input) throws UnsupportedEncodingException
    {
        if (input == null) throw new NullPointerException();
        return asHex(input.getBytes());
    }
 
    public static String hexToString(String txtInHex)
    {
        byte [] txtInByte = new byte [txtInHex.length() / 2];
        int j = 0;
        for (int i = 0; i < txtInHex.length(); i += 2)
        {
                txtInByte[j++] = Byte.parseByte(txtInHex.substring(i, i + 2), 16);
        }
        return new String(txtInByte);
    }
 
    public static String asHex(byte[] buf)
    {
        char[] chars = new char[2 * buf.length];
        for (int i = 0; i < buf.length; ++i)
        {
        	int v = buf[i] & 0xFF;
            chars[2 * i] = HEX_CHARS[v >>> 4];
            chars[2 * i + 1] = HEX_CHARS[v & 0x0F];
        }
        return new String(chars);
    }
	// print log file
	public static void printLogger(ISOMsg isoMsg) throws ISOException{
		logger.info("---------- Output ISO Message ----------");
		try {
			logger.info("MTI : "+isoMsg.getMTI()+" - HEX : "+stringToHex(isoMsg.getMTI()));
		} catch (UnsupportedEncodingException e1) {
			logger.info("Exception occur", e1);
		}
		for(int i=1;i<=isoMsg.getMaxField();i++){
			if(isoMsg.hasField(i)){
				String field = isoMsg.getString(i);
				try {
					logger.info("Field - "+ i + " - Length : "+field.length() +" - Value :" + field +" - HEX :"+stringToHex(field));
				} catch (UnsupportedEncodingException e) {
					logger.info("Exception occur", e);
				}
			}
		}
	}
	
	public static ISOMsg bytesToISOMsg(byte[] data){
		GenericPackager packager = MessageDefinition.getGenericPackager();
		ISOMsg isoMsg = new ISOMsg();
		isoMsg.setPackager(packager);
		byte[] raw = UtilPackage.extractMessage(data);
		
		System.out.println(new String(raw));
		try {
			isoMsg.unpack(raw);
			UtilPackage.printLogger(isoMsg);
		} catch (ISOException e) {
			logger.info("Exception occured", e);
		}
		return isoMsg;
	}
	// public list to array
	public static Object[][] membersToArray(List<Member> members){
		int size = members.size();
		Object[][] objs = new Object[size][5];
		for(int i =0;i<size;i++){
			Member mem = members.get(i);
			objs[i][0] = mem.getId();
			objs[i][1] = mem.getIin();
			objs[i][2] = mem.getMemId();
			objs[i][3] = mem.getName();
			objs[i][4] = mem.getLocation();
		}
		return objs;
	}
	public static Object[][] binsTomArray(List<Bin> bin) {
		int size = bin.size();
		Object[][] objs = new Object[size][4];
		for(int i=0;i<size;i++){
			Bin bi = bin.get(i);
			objs[i][0] = bi.getId();
			objs[i][1] = bi.getBin();
			objs[i][2] = bi.getType();
			objs[i][3] = bi.getIin();
		}
		return objs;
	}
	public static Object[][] cardAccountToArray(List<CardAccount> list){
		int size = list.size();
		Object[][] objs = new Object[size][9];
		for(int i=0;i<size;i++){
			CardAccount acct = list.get(i);
			objs[i][0] = acct.getId();
			objs[i][1] = acct.getCard();
			objs[i][2] = acct.getAmtType();
			objs[i][3] = acct.getCurr();
			objs[i][4] = acct.getFlag();
			objs[i][5] = acct.getBal();
			objs[i][6] = acct.getExpDate();
			objs[i][7] = acct.getCav();
			objs[i][8] = acct.getBin();
		}
		return objs;
	}
	public static Object[][] casesToArray(List<Case> list){
		int size = list.size();
		Object[][] objs = new Object[size][5];
		for(int i=0;i<size;i++){
			Case c = list.get(i);
			objs[i][0] = c.getId();
			objs[i][1] = c.getMode();
			objs[i][2] = c.getCode();
			objs[i][3] = c.getName();
			objs[i][4] = c.getRemark();
		}
		return objs;
	}
}
